home *** CD-ROM | disk | FTP | other *** search
- /* Modified version of Nico's ppLoadData */
-
- #include <pragmas.h>
- #include <libraries/dosextens.h>
- #include <exec/memory.h>
-
- #define SAFETY 8 /* Safety decrunch margin */
-
- extern int pp_DecrunchBuffer(UBYTE *,UBYTE *,int *);
- extern UBYTE *fragallocabs(int,int,UBYTE *);
- extern void fragfree(UBYTE *,int,int);
-
- #asm
- ;
- ; What follows is Nico's own decrunch routine (v2.0). I couldn't get the
- ; in-library version to work. How about fixing the .fd file, Nico?!
- ;
- ; The code has undergone some optimization and application-speciffic
- ; modification by myself. Nothing too radical, but should do better than
- ; Nico's own code in most cases. Considered doing a Forbid() around tight
- ; loops, but dropped the idea (too hostile towards the rest of the system).
- ;
-
- _pp_DecrunchBuffer:
- movem.l d2-d7/a2-a3/a5,-(sp) ; /mich: Only preserve
- move.l 36+4(a7),a0 ; relevant registers
- move.l 36+8(a7),a3
- move.l 36+12(a7),a5
- ; ' /mich: dropped 'move.l 36+16(a7),a6'
- bsr.s Decrunch
- movem.l (sp)+,d2-d7/a2-a3/a5
- rts
-
- ; a3 -> file, a0 -> longword after crunched, a5 -> ptr to eff.
- ; destroys a0-a6 and d0-d7 (/mich: no longer entirely true)
- Decrunch: moveq #3,d6
- moveq #7,d7
- moveq #1,d5
- move.l d5,d4 ; /mich: Constant '#1' in d4
- move.l a3,a2 ; remember start of file
- move.l -(a0),d1 ; get file length and empty bits
- tst.b d1
- beq.s NoEmptyBits
- bsr.s ReadBit ; this will always get the next long (D5 = 1)
- sub.b d4,d1 ; /mich: Use constant '#1'
- lsr.l d1,d5 ; get rid of empty bits
- NoEmptyBits: lsr.l #8,d1
- add.l d1,a3 ; a3 = endfile
- CheckCrunch: bsr.s ReadBit ; check if crunch or normal
- bcs.s CrunchedBytes
- NormalBytes: moveq #0,d2
- Read2BitsRow: move.l d4,d0 ; /mich: Use constant '#1'
- bsr.s ReadD1
- add.w d1,d2
- cmp.w d6,d1
- beq.s Read2BitsRow
- ReadNormalByte: moveq #7,d0
- bsr.s ReadD1
- move.b d1,-(a3)
- dbf d2,ReadNormalByte
- cmp.l a3,a2
- bcs.s CrunchedBytes
- rts
-
- ReadBit: lsr.l d4,d5 ; this will also set X if d5 becomes zero
- beq.s GetNextLong ; /mich: Use constant '#1' (previous line)
- rts
-
- GetNextLong: move.l -(a0),d5
- roxr.l d4,d5 ; X-bit set by lsr above
- rts ; /mich: Use constant '#1' (previous line)
-
- ReadD1sub: sub.w d4,d0 ; /mich: Use constant '#1'
- ReadD1: moveq #0,d1
- ReadBits: lsr.l d4,d5 ; this will also set X if d5 becomes zero
- beq.s GetNext ; /mich: Use constant '#1' (previous line)
- RotX: roxl.l d4,d1 ; /mich: Use constant '#1'
- dbf d0,ReadBits
- rts
-
- GetNext: move.l -(a0),d5
- roxr.l d4,d5 ; X-bit set by lsr above
- bra.s RotX ; /mich: Use constant '#1' (prev line)
-
- CrunchedBytes: move.l d4,d0 ; /mich: Use constant '#1'
- bsr.s ReadD1 ; read code
- moveq #0,d0
- move.b 0(a5,d1.w),d0 ; get number of bits of offset
- move.w d1,d2 ; d2 = code = length-2
- cmp.w d6,d2 ; if d2 = 3 check offset bit and read length
- bne.s ReadOffset
- bsr.s ReadBit ; read offset bit (long/short)
- bcs.s LongBlkOffs
- moveq #7,d0
- LongBlkOffs: bsr.s ReadD1sub
- move.w d1,d3 ; d3 = offset
- Read3BitsRow: moveq #2,d0
- bsr.s ReadD1
- add.w d1,d2 ; d2 = length-1
- cmp.w d7,d1 ; cmp with #7
- beq.s Read3BitsRow
- bra.s DecrunchBlock
-
- ReadOffset: bsr.s ReadD1sub ; read offset
- move.w d1,d3 ; d3 = offset
- DecrunchBlock: add.w d4,d2 ; /mich: Use constant '#1'
- 1$ move.b 0(a3,d3.w),-(a3)
- dbf d2,1$
- EndOfLoop: ; /mich: dropped 'move.w a3,(a6)'
- cmp.l a3,a2
- bcs CheckCrunch
- rts
- #endasm
-
- myPPLoadData(register BPTR filehandle,register UBYTE **mem,register *size)
- {
- int efficiency,decrunched;
- register crunlen;
- register UBYTE *memgot;
- register returnval = 1;
-
- Read(filehandle,(char *)&efficiency,sizeof(int));
- Seek(filehandle,-sizeof(int),OFFSET_END);
- Read(filehandle,(char *)&decrunched,sizeof(int));
-
- if (memgot = AllocMem((decrunched >>= 8) + SAFETY,MEMF_PUBLIC))
- {
- UBYTE *filebody;
-
- Forbid();
- FreeMem(memgot,decrunched + SAFETY);
- filebody = fragallocabs(decrunched,10240,memgot+SAFETY);
- memgot = AllocAbs(SAFETY,memgot);
- Permit();
-
- crunlen = Seek(filehandle,8,OFFSET_BEGINNING) - 8;
-
- if (Read(filehandle,(char *)memgot,crunlen) == crunlen)
- {
- pp_DecrunchBuffer(memgot+crunlen,memgot+SAFETY,&efficiency);
-
- FreeMem(memgot,SAFETY);
-
- *mem = filebody;
- *size = decrunched;
-
- returnval = 0;
- }
- else
- {
- FreeMem(memgot,SAFETY);
- fragfree(filebody,decrunched,10240);
- }
- }
-
- return(returnval);
- }
-